package com.ruiysoft.service.statement.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruiysoft.controller.wx.api.WeChatApi;
import com.ruiysoft.controller.wx.dto.DoTransferDto;
import com.ruiysoft.controller.wx.res.TransferredResponse;
import com.ruiysoft.entity.statement.StatementShop;
import com.ruiysoft.entity.statement.StatementShopDetail;
import com.ruiysoft.mapper.statement.StatementShopMapper;
import com.ruiysoft.pub.core.Result;
import com.ruiysoft.service.statement.IStatementShopDetailService;
import com.ruiysoft.service.statement.IStatementShopService;
import com.ruiysoft.service.statement.bean.StatementCondition;
import com.ruiysoft.service.statement.consts.StatementAuditStatus;
import com.ruiysoft.service.statement.consts.StatementStatus;
import com.ruiysoft.service.statement.consts.StatementType;
import com.ruiysoft.util.TradeNoUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liyahui
 * @since 2018-12-01
 */
@Service
public class StatementShopServiceImpl extends ServiceImpl<StatementShopMapper, StatementShop> implements IStatementShopService {
    private static final Logger log = LoggerFactory.getLogger(StatementShopServiceImpl.class);
    @Resource
    private IStatementShopDetailService detailService;
    @Resource
    private WeChatApi weChatApi;

    @Override
    public Long selectSumMoney(StatementCondition condition) {
        return selectSumMoney(getWrapper(condition));
    }

    @Override
    @Transactional
//    @LockAction(value = "#shopId", lockType = LockType.REENTRANT_LOCK, waitTime = 30000)
    public void withdrawable(Long money, Long shopId, Long userId) {
        if (money <= 100) {
            throw new IllegalArgumentException("提现金额必须大于1元。");
        }
        Long withdrawable = selectSumMoney(new StatementCondition().setShopId(shopId).setArrivalDateLast(new Date()).setFreeze(false));
        if (withdrawable > money) {
            throw new RuntimeException("提现金额超出可提现金额");
        }
        Date now = new Date();
        StatementShop statement = new StatementShop()
                .setTradeDate(now)
                //需要设置到账时间，不然可提现金额计算有问题
                .setArrivalDate(now)
                .setMoney(-money).setTradeNo(TradeNoUtil.getTransactionNo())
                .setShopId(shopId).setSummary("店铺提现")
                .setType(StatementType.expenditure.getIndex())
                .setFreeze(false);
        save(statement);

        StatementShopDetail detail = new StatementShopDetail()
                .setShopId(shopId)
                .setStatus(StatementStatus.START.getIndex())
                .setStatementId(statement.getId())
                .setWorkDate(new Date());
        detailService.save(detail);

        expenditure(statement, userId, StatementAuditStatus.SUCCESS, "");
    }

    @Override
    @Transactional
//    @LockAction(value = "#shopId", lockType = LockType.REENTRANT_LOCK, waitTime = 30000)
    public void expenditure(StatementShop statement, Long userId, StatementAuditStatus auditStatus, String info) {

        if (Objects.equals(auditStatus, StatementAuditStatus.SUCCESS)) {
            Result<TransferredResponse> result = weChatApi.doTransfer(new DoTransferDto()
                    //0.6%手续费
                    .setAmount(new BigDecimal(-statement.getMoney()).multiply(new BigDecimal("0.994")).setScale(0, BigDecimal.ROUND_CEILING))
//                .setShopId(statement.getShopId())
                    .setPersonnelId(userId)
                    .setTransactionNo(statement.getTradeNo()).setDesc("超级微商代收代付"));

            log.info("调用提现返回--{}", JSONObject.toJSON(result));
            if (!result.isSuccess()) {
                log.info("调用提现返回失败--{}", JSONObject.toJSON(result));
//            updateById(statement.setFreeze(true));
                updateById(statement.setSummary(JSONObject.toJSONString(result)));
                throw new RuntimeException("提现失败, 请联系管理员.");

            } else {
                String voucherNo = result.getData() != null ? result.getData().getPaymentNo() : "";
                StatementShopDetail detail1 = new StatementShopDetail()
                        .setShopId(statement.getShopId())
                        .setStatus(StatementStatus.END.getIndex())
                        .setStatementId(statement.getId())
                        .setVoucherNo(voucherNo)
                        .setAuditStatus(auditStatus.getIndex())
                        .setWorkDate(new Date());

                detailService.save(detail1);
            }
        } else if (Objects.equals(auditStatus, StatementAuditStatus.FAIL)) {
            updateById(statement.setFreeze(true));
            StatementShopDetail detail1 = new StatementShopDetail()
                    .setShopId(statement.getShopId())
                    .setStatus(StatementStatus.END.getIndex())
                    .setStatementId(statement.getId())
                    .setAuditStatus(auditStatus.getIndex())
                    .setVoucherPath(info)
                    .setWorkDate(new Date());

            detailService.save(detail1);

        } else if (Objects.equals(auditStatus, StatementAuditStatus.PENDING)) {
            StatementShopDetail detail = new StatementShopDetail()
                    .setShopId(statement.getShopId())
                    .setStatus(StatementStatus.ON_THE_WAY.getIndex())
                    .setStatementId(statement.getId())
                    .setAuditStatus(auditStatus.getIndex())
                    .setWorkDate(new Date());

            detailService.save(detail);
        }
    }

    private Long selectSumMoney(QueryWrapper<StatementShop> wrapper) {
        Map<String, Object> map = getMap(wrapper.select("sum(money) sum"));
        return map != null && !map.isEmpty() ? ((BigDecimal) map.get("sum")).longValue() : 0;
    }

    private QueryWrapper<StatementShop> getWrapper(StatementCondition condition) {
        return new QueryWrapper<StatementShop>()
                .eq(condition.getShopId() != null, "shop_id", condition.getShopId())
//                .eq(condition.getUserId()!=null,"user_id",condition.getUserId())
                .eq(condition.getFreeze() != null, "is_freeze", condition.getFreeze())
                .eq(condition.getType() != null, "type", condition.getType() != null ? condition.getType().getIndex() : null)
                .lt(condition.getArrivalDateLast() != null, "arrival_date", condition.getArrivalDateLast())
                .isNotNull(condition.getArrivalDateLast() != null, "arrival_date")
                .orderBy(false, StringUtils.isNotBlank(condition.getOrderByClause()), condition.getOrderByClause());
    }


}
